<template>
  <div class="script-manager">
    <page-header
      title="脚本管理"
      description="管理自动化任务的脚本文件,支持脚本的上传、编辑、删除等操作。"
    >
      <el-input v-model="searchQuery" placeholder="搜索脚本..." class="search-input" clearable>
        <template #prefix>
          <el-icon><Search /></el-icon>
        </template>
      </el-input>
    </page-header>

    <div class="content-wrapper">
      <!-- 文件管理器视图 -->
      <div class="file-grid" v-loading="loading">
        <div
          v-for="script in filteredScripts"
          :key="script.ID"
          class="file-item"
          @click.stop="handleSelect(script)"
          @dblclick.stop.prevent="handleEdit(script)"
          :class="{ selected: selectedScript?.ID === script.ID }"
          @contextmenu.prevent="handleContextMenu($event, script)"
        >
          <el-icon class="file-icon"><Document /></el-icon>
          <div class="file-info">
            <div class="file-name" :title="script.name">{{ script.name }}</div>
            <div class="file-meta">
              <div class="meta-tags">
                <el-tag size="small">{{ script.version }}</el-tag>
                <el-tag size="small" type="info" v-if="script.type">{{ script.type }}</el-tag>
                <el-tag size="small" type="success" v-if="script.author">{{
                  script.author
                }}</el-tag>
              </div>
              <span class="update-time">{{ script.latestUpdateTime }}</span>
            </div>
            <div class="description" v-if="script.description">
              {{ script.description }}
            </div>
          </div>
        </div>
      </div>

      <!-- 右键菜单 -->
      <div v-show="contextMenuVisible" class="context-menu" :style="contextMenuStyle" @click.stop>
        <div class="menu-list">
          <div class="menu-item" @click="handleMenuItemClick('edit')">
            <el-icon><Edit /></el-icon>编辑
          </div>
          <div class="menu-item" @click="handleMenuItemClick('download')">
            <el-icon><Download /></el-icon>下载
          </div>
          <div class="menu-item divided" @click="handleMenuItemClick('delete')">
            <el-icon><Delete /></el-icon>删除
          </div>
        </div>
      </div>

      <!-- 分页 -->
      <div class="pagination">
        <TablePagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[12, 24, 36, 48]"
          :total="total"
          layout="total, sizes, prev, pager, next"
          :teleported="false"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </div>

    <!-- 脚本编辑器 -->
    <script-editor v-model="editorVisible" :script="currentScript" @success="handleEditSuccess" />

    <floating-action-button tooltip="上传脚本" @click="handleUpload" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Document, Edit, Download, Delete, Search, Upload } from '@element-plus/icons-vue'
import { readFileAsBase64 } from '@/utils/file'
import PageHeader from '@/components/common/PageHeader.vue'
import { taskService } from '@/api/taskService'
import type { Script } from '@/api/types'
import ScriptEditor from '@/components/task/ScriptEditor.vue'
import { debounce } from 'lodash-es'
import { encode } from '@/utils/base64'
import FloatingActionButton from '@/components/common/FloatingActionButton.vue'
import TablePagination from '@/components/common/TablePagination.vue'

const loading = ref(false)
const scripts = ref<Script[]>([])
const searchQuery = ref('')
const currentPage = ref(1)
const pageSize = ref(24)
const total = ref(0)
const selectedScript = ref<Script | null>(null)
const contextMenuVisible = ref(false)
const editorVisible = ref(false)
const currentScript = ref<Script>()
const contextMenuStyle = ref('')

// 过滤后的脚本列表
const filteredScripts = computed(() => {
  if (!searchQuery.value) return scripts.value
  const query = searchQuery.value.toLowerCase()
  return scripts.value.filter((script) => script.name.toLowerCase().includes(query))
})

// 获取脚本列表
const fetchScripts = async () => {
  loading.value = true
  try {
    const data = await taskService.getScripts({
      page: currentPage.value,
      pageSize: pageSize.value,
    })
    scripts.value = data.items
    total.value = data.total
  } catch (err) {
    console.error('获取脚本列表失败:', err)
    ElMessage.error('获取脚本列表失败')
  } finally {
    loading.value = false
  }
}

// 处理选择
const handleSelect = debounce((script: Script) => {
  selectedScript.value = script
}, 200)

// 处理右键菜单
const handleContextMenu = (event: MouseEvent, script: Script) => {
  event.preventDefault()
  selectedScript.value = script
  contextMenuVisible.value = true
  contextMenuStyle.value = `
    position: fixed;
    left: ${event.clientX}px;
    top: ${event.clientY}px;
    z-index: 2000;
  `
}

// 添加点击空白区域关闭右键菜单
const handleClickOutside = (event: MouseEvent) => {
  if (contextMenuVisible.value) {
    contextMenuVisible.value = false
  }
}

// 处理上传脚本
const handleUpload = async () => {
  try {
    const input = document.createElement('input')
    input.type = 'file'
    input.accept = '.sh,.py,.js'
    input.onchange = async (e) => {
      const file = (e.target as HTMLInputElement).files?.[0]
      if (!file) return

      loading.value = true
      const content = await readFileAsBase64(file)
      await taskService.createScript({
        name: file.name,
        version: 'v1.0',
        author: 'admin',
        description: '这个人很懒,什么都没留下...',
        content,
      })
      ElMessage.success('上传成功')
      fetchScripts()
    }
    input.click()
  } catch (err) {
    console.error('上传失败:', err)
    ElMessage.error('上传失败')
  } finally {
    loading.value = false
  }
}

// 处理下载
const handleDownload = async (script: Script) => {
  try {
    const blob = await taskService.downloadScript(script.ID)
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = script.name
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
  } catch (err) {
    console.error('下载失败:', err)
    ElMessage.error('下载失败')
  }
}

// 处理编辑
const handleEdit = (script: Script) => {
  currentScript.value = {
    ...script,
    id: script.id,
    content: script.content || '',
  }
  editorVisible.value = true
}

// 处理菜单命令
const handleCommand = async (command: string) => {
  if (!selectedScript.value) return

  switch (command) {
    case 'edit':
      handleEdit(selectedScript.value)
      break
    case 'download':
      handleDownload(selectedScript.value)
      break
    case 'delete':
      handleDelete(selectedScript.value)
      break
  }
}

// 处理删除
const handleDelete = async (script: Script) => {
  try {
    await ElMessageBox.confirm(`确认删除脚本 ${script.name}？`, '提示', {
      type: 'warning',
    })
    await taskService.deleteScript(script.id)
    ElMessage.success('删除成功')
    fetchScripts()
  } catch (err) {
    if (err !== 'cancel') {
      console.error('删除脚本失败:', err)
      ElMessage.error('删除失败')
    }
  }
}

// 处理分页
const handleSizeChange = (size: number) => {
  pageSize.value = size
  currentPage.value = 1
  fetchScripts()
}

const handleCurrentChange = (page: number) => {
  currentPage.value = page
  fetchScripts()
}

// 处理编辑成功
const handleEditSuccess = () => {
  fetchScripts()
}

// 处理菜单项点击
const handleMenuItemClick = (command: string) => {
  contextMenuVisible.value = false
  handleCommand(command)
}

onMounted(() => {
  fetchScripts()
  document.addEventListener('click', handleClickOutside)
})

onBeforeUnmount(() => {
  document.removeEventListener('click', handleClickOutside)
})
</script>

<style scoped lang="scss">
.script-manager {
  position: relative;
  height: 100%;

  .content-wrapper {
    position: relative;
    background: #fff;
    border-radius: 4px;
    min-height: calc(100% - 100px);
    padding: 24px 24px 56px;

    .file-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
      gap: 16px;
      padding: 8px;

      .file-item {
        height: 80px;
        padding: 12px;
        border-radius: 4px;
        border: 1px solid var(--el-border-color-lighter);
        cursor: pointer;
        transition: all 0.2s;
        display: flex;
        align-items: center;
        gap: 12px;
        user-select: none;

        &:hover {
          background-color: var(--el-fill-color-light);
          border-color: var(--el-border-color-darker);
        }

        &.selected {
          background-color: var(--el-color-primary-light-9);
          border-color: var(--el-color-primary);
        }

        .file-icon {
          font-size: 32px;
          color: var(--el-color-info);
        }

        .file-info {
          flex: 1;
          min-width: 0;

          .file-name {
            font-size: 14px;
            color: var(--el-color-primary);
            font-weight: 500;
            margin-bottom: 4px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;

            &:hover {
              color: var(--el-color-primary-dark-2);
            }
          }

          .file-meta {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-top: 6px;

            .meta-tags {
              display: flex;
              gap: 8px;
              align-items: center;

              :deep(.el-tag) {
                border-radius: 2px;

                &.el-tag--info {
                  background-color: var(--el-color-info-light-9);
                  border-color: var(--el-color-info-light-5);
                  color: var(--el-color-info);
                }

                &.el-tag--success {
                  background-color: var(--el-color-success-light-9);
                  border-color: var(--el-color-success-light-5);
                  color: var(--el-color-success);
                }
              }
            }

            .update-time {
              font-size: 12px;
              color: var(--el-text-color-secondary);
            }
          }

          .description {
            margin-top: 6px;
            font-size: 12px;
            color: var(--el-text-color-secondary);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
        }
      }
    }

    .pagination {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      padding: 12px 24px;
      border-top: 1px solid var(--el-border-color-lighter);
      display: flex;
      justify-content: flex-end;
    }
  }

  .context-menu {
    position: fixed;
    background: white;
    border-radius: 4px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    padding: 4px 0;
    min-width: 120px;
    z-index: 2000;

    .menu-list {
      .menu-item {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 8px 16px;
        font-size: 14px;
        cursor: pointer;
        color: var(--el-text-color-regular);
        transition: all 0.3s;

        &:hover {
          background-color: var(--el-color-primary-light-9);
          color: var(--el-color-primary);
        }

        .el-icon {
          margin: 0;
        }

        &.divided {
          border-top: 1px solid var(--el-border-color-lighter);
          margin-top: 4px;
          padding-top: 8px;
        }
      }
    }
  }
}
</style>
